/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xui_lib.component.edittext;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.InputAttribute;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.components.element.VectorElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Point;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.util.ElementHelper;

import java.util.ArrayList;

/**
 * PasswordEditText
 *
 * @since 2021-03-24
 */
public class PasswordEditText extends TextField implements Component.FocusChangedListener,
    Text.TextObserver, Component.TouchEventListener {
    private static final int FOUR = 4;
    private static final int SIX = 6;
    private static final int TWOZERO = 20;
    private static final int TWOONE = 21;
    private static final int TWO = 2;

    /**
     * 增大点击区域
     */
    private int mExtraClickArea;
    /**
     * 删除按钮的引用
     */
    private VectorElement mClearDrawable;
//    private int width;
//    private int height;
//    private AttrSet attrSet;
    private ArrayList<ClearEditText.OnTextCursorChangedListener> textCursorChangedListeners = new ArrayList<>();
    private ArrayList<ClearEditText.OnFocusChangedListener> focusChangedListeners = new ArrayList<>();
    private boolean lookFlag = false;

    private Paint paint = new Paint();

    {
        paint.setStyle(Paint.Style.STROKE_STYLE);
        paint.setStrokeWidth(FOUR);
    }

    private Point start;
    private Point end;
    private boolean isInputError = false;

    /**
     * 构造函数
     *
     * @param context
     */
    public PasswordEditText(Context context) {
        super(context);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     */
    public PasswordEditText(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public PasswordEditText(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        setEstimateSizeListener(new EstimateSizeListener() {
            @Override
            public boolean onEstimateSize(int i, int i1) {
                int width1 = EstimateSpec.getSize(i);
                int height1 = EstimateSpec.getSize(i1);
                start = new Point(0, height1 - paint.getStrokeWidth());
                end = new Point(width1, height1 - paint.getStrokeWidth());
                return false;
            }
        });
        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                if (isFocused()) {
                    paint.setStrokeWidth(SIX);
                    if (isInputError) {
                        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
                    } else {
                        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_blue_light));
                    }
                    paint.setMaxLines(1);
                    canvas.drawLine(start, end, paint);
                    initAttrs(getContext());
                } else {
                    if (isInputError) {
                        paint.setStrokeWidth(SIX);
                        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
                    } else {
                        paint.setStrokeWidth(FOUR);
                        paint.setColor(ElementHelper.getColor(getContext(),
                            ResourceTable.Color_xui_config_color_gray_10));
                    }
                    paint.setMaxLines(1);
                    canvas.drawLine(start, end, paint);
                    initAttrs(getContext());
                }
            }
        });
        initView();
    }

    private void initView() {
        setCursorChangedListener(new CursorChangedListener() {
            @Override
            public void onCursorChange(TextField textField, int i, int i1) {
                if (textCursorChangedListeners.size() > 0) {
                    for (ClearEditText.OnTextCursorChangedListener listener : textCursorChangedListeners) {
                        listener.onCursorChange(textField, i, i1);
                    }
                }
            }
        });
        setFocusChangedListener(new FocusChangedListener() {
            @Override
            public void onFocusChange(Component component, boolean isFocused) {
                if (focusChangedListeners.size() > 0) {
                    for (ClearEditText.OnFocusChangedListener listener : focusChangedListeners) {
                        listener.onFocusChange(component, isFocused);
                    }
                }
                invalidate();
            }
        });
        setTextInputType(InputAttribute.PATTERN_PASSWORD);

    }

    /**
     * setInputError
     *
     * @param isInputError1
     */
    public void setInputError(boolean isInputError1) {
        this.isInputError = isInputError1;
        invalidate();
    }

    public boolean isInputError() {
        return this.isInputError;
    }

    /**
     * addTextCursorChangedListener
     *
     * @param listener
     */
    public void addTextCursorChangedListener(ClearEditText.OnTextCursorChangedListener listener) {
        if (!textCursorChangedListeners.contains(listener)) {
            this.textCursorChangedListeners.add(listener);
        }
    }

    /**
     * removeTextCursorChangedListener
     *
     * @param listener
     */
    public void removeTextCursorChangedListener(ClearEditText.OnTextCursorChangedListener listener) {
        this.textCursorChangedListeners.remove(listener);
    }

    /**
     * addOnFocusChangedListener
     *
     * @param listener
     */
    public void addOnFocusChangedListener(ClearEditText.OnFocusChangedListener listener) {
        if (!focusChangedListeners.contains(listener)) {
            this.focusChangedListeners.add(listener);
        }
    }

    /**
     * removeOnFocusChangedListener
     *
     * @param listener
     */
    public void removeOnFocusChangedListener(ClearEditText.OnFocusChangedListener listener) {
        this.focusChangedListeners.remove(listener);
    }

    @Override
    public void setText(String text) {
        super.setText(text);
        setClearIconVisible(false);
    }

    /**
     * 当ClearEditText焦点发生变化的时候，判断里面字符串长度设置清除图标的显示与隐藏
     *
     * @param component
     * @param b
     */
    @Override
    public void onFocusChange(Component component, boolean b) {
        if (b) {
            int length = getText() != null ? getText().length() : 0;
            setClearIconVisible(length > 0);
        } else {
            setClearIconVisible(false);
        }
    }

    @Override
    public void onTextUpdated(String s, int i, int i1, int i2) {
        setClearIconVisible(s.length() > 0); // s:指示当前文本
        // i:指示要添加的文本的开始位置 i1:指示旧文本的长度 i2:指示要添加的文本的长度
    }

    private void initAttrs(Context context) {
        mExtraClickArea = AttrHelper.vp2px(TWOZERO, context);
        if (mClearDrawable == null) {
            mClearDrawable = new VectorElement(context,
                ResourceTable.Graphic_pet_icon_visibility_off_dp); // 获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
        }
        mClearDrawable.setBounds(0, 0, AttrHelper.vp2px(TWOONE, getContext()), AttrHelper.vp2px(TWOONE, getContext()));
        setClearIconVisible(false); // 设置为隐藏图标
        onFocusChange(this, true); // 设置焦点改变的监听
        addTextObserver(this); // 设置输入框里面内容发生改变的监听
        setTouchEventListener(this);
    }

    /**
     * 设置清除图标的显示与隐藏，调用setAroundElementsPadding为EditText绘制上去
     *
     * @param visible
     */
    protected void setClearIconVisible(boolean visible) {
        VectorElement endBitmap = visible ? mClearDrawable : null;
        lookFlag = visible;
        setAroundElementsRelative(null, null, endBitmap, null);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        if (getAroundElementsRelative()[TWO] != null && touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
            boolean touchable = isTouchable(touchEvent);
            if (touchable) {
                if (lookFlag) {
                    setTextInputType(InputAttribute.PATTERN_TEXT);
                    mClearDrawable = new VectorElement(getContext(), ResourceTable.Graphic_pet_icon_visibility_dp);
                    mClearDrawable.setBounds(0, 0,
                        AttrHelper.vp2px(TWOONE, getContext()), AttrHelper.vp2px(TWOONE, getContext()));
                    setAroundElementsRelative(null, null, mClearDrawable, null);
                    lookFlag = false;
                } else {
                    setTextInputType(InputAttribute.PATTERN_PASSWORD);
                    mClearDrawable = new VectorElement(getContext(),
                        ResourceTable.Graphic_pet_icon_visibility_off_dp);
                    mClearDrawable.setBounds(0, 0,
                        AttrHelper.vp2px(TWOONE, getContext()), AttrHelper.vp2px(TWOONE, getContext()));
                    setAroundElementsRelative(null, null, mClearDrawable, null);
                    lookFlag = true;
                }
            }
        }
        return true;
    }

    private boolean isTouchable(TouchEvent event) {
        if (isRtl()) {
            return event.getPointerScreenPosition(0).getX() > getPaddingLeft() - mExtraClickArea
                && event.getRadius(0) < getPaddingLeft() + mClearDrawable.getWidth() + mExtraClickArea;
        } else {
            return event.getPointerScreenPosition(0).getX()
                > getWidth() - getPaddingRight() - mClearDrawable.getWidth() - mExtraClickArea
                && event.getRadius(0) < getWidth() - getPaddingRight() + mExtraClickArea;
        }
    }

    /**
     * OnTextCursorChangedListener
     *
     * @since 2021-03-24
     */
    public interface OnTextCursorChangedListener {
        /**
         * onCursorChange
         *
         * @param textField
         * @param posStart
         * @param posAfter
         */
        void onCursorChange(TextField textField, int posStart, int posAfter);
    }

    /**
     * OnFocusChangedListener
     *
     * @since 2021-03-24
     */
    public interface OnFocusChangedListener {
        /**
         * onFocusChange
         *
         * @param component
         * @param isFocused
         */
        void onFocusChange(Component component, boolean isFocused);
    }
}

